package service

import (
	"gorm.io/gorm"
	"sort"
	"strconv"
	"strings"
	"view-crawler-backend/internal/biz_error"
	"view-crawler-backend/internal/bo"
	"view-crawler-backend/internal/dao"
	"view-crawler-backend/internal/dao/entity"
	"view-crawler-backend/internal/tools"
)

func CreateTask(task *entity.Task, taskCategories []int64) (int64, error) {
	// 检查任务名是否已经被使用
	isTaskNameInUse, err := dao.IsTaskNameInUse(dao.DB, task.TaskName)
	if err != nil {
		return 0, err
	}
	if isTaskNameInUse {
		return 0, biz_error.TaskNameUsedError
	}

	// 生成taskId
	taskId := tools.GenerateId()
	task.TaskId = taskId

	// 插入数据
	if err := dao.DB.Transaction(func(tx *gorm.DB) error {
		// 记录任务模板
		if err := dao.AddTask(tx, task); err != nil {
			return err
		}
		// 记录任务分类
		taskCategoryList := make([]entity.TaskCategory, len(taskCategories))
		for i, category := range taskCategories {
			taskCategoryList[i] = entity.TaskCategory{
				TaskId:     taskId,
				CategoryId: category,
			}
		}
		if err := dao.BatchAddTaskCategory(tx, taskCategoryList); err != nil {
			return err
		}
		return nil
	}); err != nil {
		return 0, err
	}
	return taskId, nil
}

func DeleteTask(taskId int64) error {
	return dao.DB.Transaction(func(tx *gorm.DB) error {
		if err := dao.DeleteTaskById(tx, taskId); err != nil {
			return err
		}
		if err := dao.DeleteTaskCategoryByTaskId(tx, taskId); err != nil {
			return err
		}
		if err := dao.DeleteTaskDefineById(taskId); err != nil {
			return err
		}
		// TODO 删除该任务相关的执行记录和采集到的数据
		return nil
	})
}

func UpdateTask(task *entity.Task) error {
	// 查询任务的旧类别
	categoryIdList, err := dao.QueryCategoryIdListByTaskId(dao.DB, task.TaskId)
	if err != nil {
		return err
	}
	// 构建新老类别列表，准备进行比较
	oldCategoryIdList, newCategoryIdList := []int64{}, []int64{}
	for _, category := range categoryIdList {
		oldCategoryIdList = append(oldCategoryIdList, category)
	}
	if task.Categories != nil {
		for _, categoryId := range strings.Split(*task.Categories, ",") {
			id, err := strconv.ParseInt(categoryId, 10, 64)
			if err != nil {
				return err
			}
			newCategoryIdList = append(newCategoryIdList, id)
		}
	}
	// 类别没有发生变化，只需更新task表
	if !categoryDiff(oldCategoryIdList, newCategoryIdList) {
		if err := dao.UpdateTask(dao.DB, task); err != nil {
			return err
		}
		return nil
	}
	// 同时更新task表和task_category表
	if err := dao.DB.Transaction(func(tx *gorm.DB) error {
		if err := dao.UpdateTask(tx, task); err != nil {
			return err
		}
		// 删除旧的分类
		if err := dao.DeleteTaskCategoryByTaskId(tx, task.TaskId); err != nil {
			return err
		}
		// 插入新的分类
		taskCategoryList := make([]entity.TaskCategory, len(newCategoryIdList))
		for i, categoryId := range newCategoryIdList {
			taskCategoryList[i] = entity.TaskCategory{
				TaskId:     task.TaskId,
				CategoryId: categoryId,
			}
		}
		if err := dao.BatchAddTaskCategory(tx, taskCategoryList); err != nil {
			return err
		}
		return nil
	}); err != nil {
		return err
	}
	return nil
}

func categoryDiff(oldCategoryIdList []int64, newCategoryIdList []int64) bool {
	if len(oldCategoryIdList) != len(newCategoryIdList) {
		return true
	}
	sort.Slice(oldCategoryIdList, func(i, j int) bool {
		return oldCategoryIdList[i] < oldCategoryIdList[j]
	})
	sort.Slice(newCategoryIdList, func(i, j int) bool {
		return newCategoryIdList[i] < newCategoryIdList[j]
	})
	for i := range oldCategoryIdList {
		if oldCategoryIdList[i] != newCategoryIdList[i] {
			return true
		}
	}
	return false
}

func UpdateTaskDefine(taskId int64, taskDefineBytes []byte) error {
	return dao.UpdateTaskDefine(taskId, taskDefineBytes)
}

func QueryTaskList(page, pageSize int) ([]entity.Task, int64, error) {
	tasks, err := dao.QueryTaskList(dao.DB, page, pageSize)
	if err != nil {
		return nil, 0, err
	}
	total, err := dao.QueryTaskCount(dao.DB)
	if err != nil {
		return nil, 0, err
	}
	return tasks, total, nil
}

func QueryTaskDetail(taskId int64) (*bo.TaskDetailBO, error) {
	task, err := dao.QueryTaskByTaskId(dao.DB, taskId)
	if err != nil {
		return nil, err
	}

	taskDefine, err := dao.QueryTaskDefineById(taskId)
	if err != nil {
		return nil, err
	}

	if task.Categories == nil {
		return &bo.TaskDetailBO{
			Task:       *task,
			TaskDefine: taskDefine,
		}, nil
	}
	// 查询任务的类别名
	categoryIdStrList := strings.Split(*task.Categories, ",")
	categoryIdList := make([]int64, len(categoryIdStrList))
	for i := range categoryIdList {
		parseInt, err := strconv.ParseInt(categoryIdStrList[i], 10, 64)
		if err != nil {
			return nil, err
		}
		categoryIdList[i] = parseInt
	}
	categories, err := dao.QueryCategoryByIdList(dao.DB, categoryIdList)
	if err != nil {
		return nil, err
	}
	categoryMap := make(map[int64]string)
	for _, category := range categories {
		categoryMap[category.CategoryId] = category.CategoryName
	}

	return &bo.TaskDetailBO{
		Task:        *task,
		TaskDefine:  taskDefine,
		CategoryMap: categoryMap,
	}, nil
}
